package stdslice

import "fmt"

// 这是一个错误的示例，展示了如何在函数中修改切片但没有正确传递引用
// 我们的目的是希望通过 collectAllLeftError 函数收集所有左子节点到 stack 中，并在调用的地方原地使用 stack.
// 但由于切片是值传递的，修改 stack 不会影响到外部的 stack.

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func JustTest(root *TreeNode) {
	stack := []*TreeNode{}
	collectAllLeftError(stack, root)
	fmt.Printf("%v\n", stack)
}

// 这是一个错误的实现，stack 在 collectAllLeftError 函数中被修改，但在调用后并没有反映到外部的 stack 中
// 这会导致输出的 stack 始终为空，因为 collectAllLeftError 函数中的 stack 是一个新的切片副本，因为切片的传递是值传递。
func collectAllLeftError(stack []*TreeNode, node *TreeNode) {
	stack = append(stack, node)
	for node.Left != nil {
		stack = append(stack, node.Left)
		node = node.Left
	}
}

// 正确的实现应该传递切片的指针，这样可以在函数中修改原始切片
func collectAllLeftRight(stack *[]*TreeNode, node *TreeNode) {
	*stack = append(*stack, node)
	for node.Left != nil {
		*stack = append(*stack, node.Left)
		node = node.Left
	}
}

// 调用方式
func JustTestRight(root *TreeNode) {
	stack := []*TreeNode{}
	collectAllLeftRight(&stack, root)
	fmt.Printf("%v\n", stack)
}

// 当然如果你不想传递指针，也可以使用返回值的方式来实现
func collectAllLeftRightReturn(stack []*TreeNode, node *TreeNode) [](*TreeNode) {
	stack = append(stack, node)
	for node.Left != nil {
		stack = append(stack, node.Left)
		node = node.Left
	}
	return stack
}

// 调用方式
func JustTestRightReturn(root *TreeNode) {
	stack := []*TreeNode{}
	stack = collectAllLeftRightReturn(stack, root)
	fmt.Printf("%v\n", stack)
}
